package com.zlq.cn.api;

import com.alibaba.fastjson.JSON;
import com.zlq.cn.annotations.UnPrintResult;
import com.zlq.cn.bootstrap.SignApiBootstrap;
import com.zlq.cn.util.IpUtils;
import io.swagger.annotations.ApiOperation;
import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.Duration;
import java.time.LocalDateTime;

@Slf4j
@Aspect
@Component
public class SignApiAspect {

    @Resource
    private HttpServletRequest request;

    private static final int RESULT_LENGTH = 500;

    @Around("execution(* com.zlq.cn.controller..*.*(..)) && !execution(* com.zlq.cn.controller..*.initBinder*(..))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        UnPrintResult unPrintResult = method.getAnnotation(UnPrintResult.class);
        String apiName = apiOperation != null ? apiOperation.value() : joinPoint.getSignature().getName();
        LocalDateTime beginTime = LocalDateTime.now();
        StringBuilder sb = new StringBuilder();
        sb.append("\r\n==========================================").append("\r\n");
        sb.append("Request API : ").append(apiName).append("\r\n");
        sb.append("Request Start : ").append(beginTime).append("\r\n");
        sb.append("Request IP : ").append(IpUtils.getIpAddr(request)).append("\r\n");
        sb.append("Request url : ").append(request.getRequestURL().toString()).append("\r\n");
        sb.append("Http Method : ").append(request.getMethod()).append("\r\n");
        sb.append("CLASS_METHOD : ").append(joinPoint.getTarget().getClass().getSimpleName()).append(".").append(joinPoint.getSignature().getName()).append("\r\n");
        try {
            sb.append("Params : ").append(JSON.toJSONString(joinPoint.getArgs())).append("\r\n");
        } catch (Exception e) {

        }

        Object proceed = null;
        try {
            proceed = joinPoint.proceed();
        } catch (Throwable e) {
            log.error(e.getMessage(), e);
            sb.append("Request Error : ").append(e.getMessage()).append("\r\n");
            throw e;
        } finally {
            SignApiBootstrap.remove();
            LocalDateTime endTime = LocalDateTime.now();
            if (unPrintResult == null) {
                sb.append("Request Result : ").append(JSON.toJSONString(proceed)).append("\r\n");
            }
            sb.append("Request End : ").append(endTime).append("\r\n");
            sb.append("Request Time : ").append(Duration.between(beginTime, endTime).toMillis()).append("MS").append("\r\n");
            sb.append("==========================================").append("\r\n");
            log.info(sb.toString());
        }
        return proceed;
    }
}
